#include "LightPass.h"
#include "Camera/BaseCamera.h"
#include "GameApp.h"
#include "RenderSystem.h"
#include "Scene/Engine.h"
#include "HardwareResourceManager.h"
#include "EffectTechnique.h"
#include "D3D10RenderDevice.h"

CLightPass::CLightPass()
{

}

CLightPass::~CLightPass()
{

}

void CLightPass::Init()
{
	_BuildLightEffect();
	_BuildVertexLayouts();
}

void CLightPass::UnInit()
{
	if (m_pEffect != NULL)
	{
		GetApp()->GetEngine()->GetHwResMgr()->ReleaseResource(m_pEffect);
		m_pEffect      = NULL;
		m_pLightEffect = NULL;
		m_pLightTech   = NULL;
		m_pWVPVar      = NULL;
		m_pWorldVar    = NULL;
		m_pEyePosVar   = NULL;
		m_pLightVar    = NULL;
		m_pLightType   = NULL;
	}	
}

void CLightPass::Render( std::vector<CRenderObject*> *pRenderObjs )
{
	std::vector<CRenderObject*>::iterator it = pRenderObjs->begin();
	for (; it != pRenderObjs->end(); ++it)
	{
		CRenderObject* pRenderObj = *it;
		if (pRenderObj->eType == ERENDER_OBJ_MESH)
		{
			CMeshRenderObject *pMeshObj = dynamic_cast<CMeshRenderObject*>(pRenderObj);
			_DrawMeshRenderObj(pMeshObj);
		}
	}
}

void CLightPass::BeginRender()
{
	CEngine *pEngine = GetApp()->GetEngine();
	const CMatrix& mViewMat = pEngine->GetViewMatrix();
	const CMatrix& mProjMat = pEngine->GetProjMatrix();
	m_mViewProjMat = mViewMat * mProjMat;

	ID3D10Device* pD3DDevice = GetEngine()->GetRenderDevice()->GetDevice();

	pD3DDevice->OMSetDepthStencilState(0, 0);
	float blendFactors[] = {0.0f, 0.0f, 0.0f, 0.0f};
	pD3DDevice->OMSetBlendState(0, blendFactors, 0xffffffff);

	pD3DDevice->IASetInputLayout(m_pVertexLayout);
	pD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

void CLightPass::EndRender()
{

}

void CLightPass::_BuildLightEffect()
{
	CEngine* pEngine = GetApp()->GetEngine();
	CHardwareResourceManager* pHWResMgr = pEngine->GetHwResMgr();

	std::wstring strEffectPath = GetApp()->GetResourcePath() + L"color.fx";

	m_pEffect      = pHWResMgr->CreateEffect(strEffectPath);
	m_pLightEffect = m_pEffect->GetHandle();
	m_pLightTech   = m_pLightEffect->GetTechniqueByName("ColorTech");
	m_pWVPVar      = m_pLightEffect->GetVariableByName("gWVP")->AsMatrix();
}

void CLightPass::_BuildVertexLayouts()
{
	D3D10_INPUT_ELEMENT_DESC  vertexDesc[] = 
	{
		{
			"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,    0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0
		},
		{
			"COLOR",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0
		}
	};
	D3D10_PASS_DESC passDesc;
	m_pLightTech->GetPassByIndex(0)->GetDesc(&passDesc);

	CD3D10RenderDevice* pDevice = GetApp()->GetEngine()->GetRenderDevice();
	ID3D10Device* pD3DDevice = pDevice->GetDevice();
	HR(pD3DDevice->CreateInputLayout(vertexDesc, 2, passDesc.pIAInputSignature, 
		passDesc.IAInputSignatureSize, &m_pVertexLayout));
}

void CLightPass::_DrawMeshRenderObj( CMeshRenderObject* pMeshObj )
{
	CRenderSystem* pRenderer = GetApp()->GetEngine()->GetRenderer();

	D3D10_TECHNIQUE_DESC techDesc;
	m_pLightTech->GetDesc(&techDesc);
	for (UINT32 p = 0; p < techDesc.Passes; p++)
	{
		CMatrix mWVPMat = pMeshObj->mMatrix * m_mViewProjMat;
		m_pWVPVar->SetMatrix((float*)&mWVPMat);
		m_pLightTech->GetPassByIndex(p)->Apply(0);

		pRenderer->DrawMesh(pMeshObj->pMeshBuffer);
	}
}

